package com.xizi.lotterySystem.service.Impl;

import com.xizi.lotterySystem.common.exception.ServiceException;
import com.xizi.lotterySystem.common.exception.errorCode.ServiceErrorCodeConstants;
import com.xizi.lotterySystem.common.pojo.Constants;
import com.xizi.lotterySystem.controller.UserController;
import com.xizi.lotterySystem.controller.param.UserMessageLoginParam;
import com.xizi.lotterySystem.controller.param.UserPasswordLoginParam;
import com.xizi.lotterySystem.controller.param.UserRegisterParam;
import com.xizi.lotterySystem.dao.handler.Encrypt;
import com.xizi.lotterySystem.dao.mapper.UserMapper;
import com.xizi.lotterySystem.service.IUserService;
import com.xizi.lotterySystem.service.dto.UserDTO;
import com.xizi.lotterySystem.service.dto.UserLoginDTO;
import com.xizi.lotterySystem.service.dto.UserRegisterDTO;
import com.xizi.lotterySystem.service.enumerate.UserIdentityEnum;
import com.xizi.lotterySystem.utils.JWTUtil;
import com.xizi.lotterySystem.utils.PasswordUtils;
import com.xizi.lotterySystem.utils.RedisUtil;
import com.xizi.lotterySystem.utils.RegexUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

@Service
public class UserServiceImpl implements IUserService {
    Logger log = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserRegisterDTO register(UserRegisterParam userRegisterParam) {
        //1.校验用户信息
        verifyUserRegisterParam(userRegisterParam);

        //2.密码加密
        String salt = PasswordUtils.getSalt();
        String encrypt = PasswordUtils.encrypt(userRegisterParam.getPassword(), salt);

        //3.手机号加密(TypeHandler 自动 加密，解密)
        //4.保存用户信息
        UserRegisterDTO userRegisterDTO = new UserRegisterDTO();

        userRegisterDTO.setUserName(userRegisterParam.getName());
        userRegisterDTO.setPassword(encrypt);
        userRegisterDTO.setSalt(salt);
        userRegisterDTO.setPhoneNumber(new Encrypt(userRegisterParam.getPhoneNumber()));
        userRegisterDTO.setEmail(userRegisterParam.getMail());
        userRegisterDTO.setIdentity(userRegisterParam.getIdentity());

        int row = userMapper.insertUser(userRegisterDTO);
        if(row != 1){
            throw new ServiceException(ServiceErrorCodeConstants.SQL_ERROR);
        }
        return userRegisterDTO;
    }

    @Override
    public String passwordLogin(UserPasswordLoginParam param) {
        if(!RegexUtil.checkMobile(param.getLoginName())){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        
        UserLoginDTO userLoginDTO = userMapper.selectByPhoneNumber(new Encrypt(param.getLoginName()));
        
        if(userLoginDTO == null){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }

        String inputPassword = PasswordUtils.encrypt(param.getPassword(), userLoginDTO.getSalt());

        if(!PasswordUtils.check(inputPassword,userLoginDTO.getPassword())){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_OR_PASSWORD_ERROR);
        }
        HashMap<String,Object> map = new HashMap<>();
        map.put(Constants.JWT_HEADER,userLoginDTO.getId());
        map.put(Constants.JWT_PAYLOAD,userLoginDTO.getIdentity());
        String jwt = JWTUtil.genJwt(map);

        return jwt;
    }

    @Override
    public String messageLogin(UserMessageLoginParam param) {
        if(!RegexUtil.checkMail(param.getEmail())){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }

        UserLoginDTO userLoginDTO = userMapper.selectByEmail(param.getEmail());
        if(userLoginDTO == null){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_NO_EXIST);
        }

        String verifyCode = RedisUtil.get(param.getEmail()+Constants.EMAIL_LOGIN_SUFFIX);

        if(!param.getVerificationCode().equals(verifyCode)){
            throw new ServiceException(ServiceErrorCodeConstants.VERIFICATION_CODE_ERROR);
        }

        HashMap<String,Object> map = new HashMap<>();
        map.put(Constants.JWT_HEADER,userLoginDTO.getId());
        map.put(Constants.JWT_PAYLOAD,userLoginDTO.getIdentity());
        String jwt = JWTUtil.genJwt(map);

        return jwt;
    }

    @Override
    public List<UserDTO> findUserList(UserIdentityEnum identity) {
        String identityStr = identity == null ? null : identity.name();

        List<UserDTO> userDTOList = userMapper.selectAllByIdentity(identityStr);

        return userDTOList == null ? new ArrayList<UserDTO>() : userDTOList;
    }

    // 校验  注册  用户信息
    private void verifyUserRegisterParam(UserRegisterParam param) {
        if (param == null) {
            throw new ServiceException(ServiceErrorCodeConstants.PARAM_IS_NULL);
        }
        //1.校验姓名
        if(!StringUtils.hasText(param.getName())){
            throw new ServiceException(ServiceErrorCodeConstants.NAME_ERROR);
        }

        //2.校验邮箱
        checkEmail(param.getMail());

        //3.校验电话号码
        checkPhone(param.getPhoneNumber());

        //4.校验身份
        if(UserIdentityEnum.getByValue(param.getIdentity()) == null){
            throw new ServiceException(ServiceErrorCodeConstants.IDENTITY_ERROR);
        }

        //5.校验密码
        if(param.getIdentity().equalsIgnoreCase("admin") && !RegexUtil.checkPassword(param.getPassword())){
            throw new ServiceException(ServiceErrorCodeConstants.PASSWORD_ERROR);
        }
        log.info("校验参数完成！");
    }

    private void checkPhone(String phoneNumber) {
        if(!RegexUtil.checkMobile(phoneNumber)){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_NUMBER_ERROR);
        }
        if(userMapper.selectCountByPhoneNumber(new Encrypt(phoneNumber)) > 0){
            throw new ServiceException(ServiceErrorCodeConstants.PHONE_IS_USED);
        }
    }

    private void checkEmail(String email) {
        if(!RegexUtil.checkMail(email)){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_ERROR);
        }
        if(userMapper.selectCountByEmail(email) > 0){
            throw new ServiceException(ServiceErrorCodeConstants.MAIL_IS_USED);
        }
    }
    
}
